package com.huan.study.esapi.dslapi.functionscore;

import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.Test;

/**
 * 根据多字段自定义评分
 * <a href="https://segmentfault.com/a/1190000037700644?utm_source=tag-newest">https://segmentfault.com/a/1190000037700644?utm_source=tag-newest</a>
 *
 * @author huan.fu 2021/5/27 - 上午11:17
 */
public class FunctionScoreApi {

    @Test
    public void functionScoreTest() {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 从索引那个开始返回数据
        searchSourceBuilder.from(0);
        // 查询多少条记录
        searchSourceBuilder.size(10);
        // 查询超时时间
        searchSourceBuilder.timeout(TimeValue.timeValueSeconds(20));
        searchSourceBuilder.query(
                QueryBuilders.functionScoreQuery(
                        QueryBuilders.matchAllQuery(),
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                                new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                        ScoreFunctionBuilders.fieldValueFactorFunction("数字字段")
                                                .missing(0)
                                                .factor(1.2f)
                                                .modifier(FieldValueFactorFunction.Modifier.LOG1P)),
                                new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                        /**
                                         * weight : 加权。
                                         * random_score : 随机打分。
                                         * field_value_factor : 使用字段的数值参与计算分数。
                                         * decay_function : 衰减函数 gauss, linear, exp 等。
                                         * script_score : 自定义脚本。
                                         */
                                        ScoreFunctionBuilders.fieldValueFactorFunction("数字字段")
                                                .missing(1)
                                                .factor(2.2f)
                                                .modifier(FieldValueFactorFunction.Modifier.LOG1P))
                        }
                )
                        /**
                         * 最终的分数 result_score 是由 query_score 与 func_score 进行计算而来，计算方式由参数 boost_mode 定义：
                         * multiply : 相乘（默认），result_score = query_score * function_score
                         * replace : 替换，result_score = function_score
                         * sum : 相加，result_score = query_score + function_score
                         * avg : 取两者的平均值，result_score = Avg(query_score, function_score)
                         * max : 取两者之中的最大值，result_score = Max(query_score, function_score)
                         * min : 取两者之中的最小值，result_score = Min(query_score, function_score)
                         */
                        .boostMode(CombineFunction.SUM)
                        /**
                         * 参数 score_mode 指定多个打分函数如何组合计算出新的分数：
                         * multiply : 分数相乘（默认）
                         * sum : 相加
                         * avg : 加权平均值
                         * first : 使用第一个 filter 函数的分数
                         * max : 取最大值
                         * min : 取最小值
                         */
                        .scoreMode(FunctionScoreQuery.ScoreMode.SUM)
        );
        System.out.println(searchSourceBuilder);
    }
}
